#!/bin/bash

# SSL证书管理系统 - Keeper (数据守护脚本) Docker版
# 专门用于容器化环境中后端 .env 文件和数据库的备份与恢复
# 
# 功能：
# - 备份容器中的后端 .env 配置文件
# - 备份 MySQL 容器数据库
# - 恢复后端 .env 配置文件到容器
# - 恢复数据库到容器
# - 列出和验证备份文件

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# 获取脚本所在目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$SCRIPT_DIR"

# 容器配置
PHP_CONTAINER="cert-php"
MYSQL_CONTAINER="cert-mysql"
CONTAINER_BACKEND_DIR="/www/cert_manager/deploy/backend"

# 目录配置
BACKUP_ROOT_DIR="$PROJECT_ROOT/keeper-backups"
ENV_BACKUP_DIR="$BACKUP_ROOT_DIR/env"
DB_BACKUP_DIR="$BACKUP_ROOT_DIR/database"

# 确保备份目录存在
mkdir -p "$ENV_BACKUP_DIR" "$DB_BACKUP_DIR"

# 日志函数
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_warning() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_prompt() { echo -e "${CYAN}[PROMPT]${NC} $1"; }

# 生成时间戳
get_timestamp() {
    date '+%Y%m%d_%H%M%S'
}

# 检查容器是否运行
check_container() {
    local container_name="$1"
    
    if ! docker ps --format '{{.Names}}' | grep -q "^${container_name}$"; then
        log_error "容器 '$container_name' 未运行"
        log_info "请使用 'docker compose up -d' 启动容器"
        return 1
    fi
    
    return 0
}

# 从容器中读取 .env 配置
read_env_from_container() {
    if ! check_container "$PHP_CONTAINER"; then
        return 1
    fi
    
    # 临时文件
    local temp_env="/tmp/cert_env_$$"
    
    # 从容器复制 .env 文件
    if docker cp "$PHP_CONTAINER:$CONTAINER_BACKEND_DIR/.env" "$temp_env" 2>/dev/null; then
        # 解析数据库配置
        DB_CONNECTION=$(grep '^DB_CONNECTION=' "$temp_env" | cut -d'=' -f2 | sed 's/["\r\n ]//g' | head -1)
        DB_HOST=$(grep '^DB_HOST=' "$temp_env" | cut -d'=' -f2 | sed 's/["\r\n ]//g' | head -1)
        DB_PORT=$(grep '^DB_PORT=' "$temp_env" | cut -d'=' -f2 | sed 's/["\r\n ]//g' | head -1)
        DB_DATABASE=$(grep '^DB_DATABASE=' "$temp_env" | cut -d'=' -f2 | sed 's/["\r\n ]//g' | head -1)
        DB_USERNAME=$(grep '^DB_USERNAME=' "$temp_env" | cut -d'=' -f2 | sed 's/["\r\n ]//g' | head -1)
        DB_PASSWORD=$(grep '^DB_PASSWORD=' "$temp_env" | cut -d'=' -f2 | sed 's/["\r\n ]//g' | head -1)
        
        # 设置默认值
        [ -z "$DB_CONNECTION" ] && DB_CONNECTION="mysql"
        [ -z "$DB_HOST" ] && DB_HOST="cert-mysql"  # Docker 网络中的容器名
        [ -z "$DB_PORT" ] && DB_PORT="3306"
        
        # 清理临时文件
        rm -f "$temp_env"
        
        log_info "数据库配置信息:"
        log_info "  连接类型: $DB_CONNECTION"
        log_info "  主机: $DB_HOST"
        log_info "  端口: $DB_PORT"
        log_info "  数据库: $DB_DATABASE"
        log_info "  用户名: $DB_USERNAME"
        
        # 验证必要的配置
        if [ -z "$DB_DATABASE" ] || [ -z "$DB_USERNAME" ]; then
            log_error "数据库配置不完整，请检查容器中的 .env 文件"
            return 1
        fi
        
        return 0
    else
        log_error "无法从容器读取 .env 文件"
        return 1
    fi
}

# 测试数据库连接（通过容器）
test_database_connection() {
    log_info "测试数据库连接..."
    
    if ! check_container "$MYSQL_CONTAINER"; then
        return 1
    fi
    
    # 通过 MySQL 容器测试连接
    if docker exec "$MYSQL_CONTAINER" mysql -u "$DB_USERNAME" -p"$DB_PASSWORD" "$DB_DATABASE" -e "SELECT 1;" >/dev/null 2>&1; then
        log_success "数据库连接测试成功"
        return 0
    else
        log_error "数据库连接失败，请检查配置和容器状态"
        return 1
    fi
}

# 备份 .env 文件
backup_env_file() {
    local timestamp="$1"
    
    if ! check_container "$PHP_CONTAINER"; then
        return 1
    fi
    
    local backup_file="$ENV_BACKUP_DIR/env_${timestamp}.backup"
    
    log_info "从容器备份 .env 文件..."
    
    # 从容器复制文件
    if docker cp "$PHP_CONTAINER:$CONTAINER_BACKEND_DIR/.env" "$backup_file" 2>/dev/null; then
        # 创建备份信息文件
        cat > "$ENV_BACKUP_DIR/env_${timestamp}.info" << EOF
备份时间: $(date '+%Y-%m-%d %H:%M:%S')
容器名称: $PHP_CONTAINER
原始文件: $CONTAINER_BACKEND_DIR/.env
备份文件: $backup_file
文件大小: $(stat -c%s "$backup_file" 2>/dev/null || stat -f%z "$backup_file" 2>/dev/null || echo "未知") 字节
MD5校验: $(md5sum "$backup_file" 2>/dev/null | cut -d' ' -f1 || md5 -q "$backup_file" 2>/dev/null || echo "未计算")
EOF
        
        log_success ".env 文件备份完成: $backup_file"
        return 0
    else
        log_error "无法从容器备份 .env 文件"
        return 1
    fi
}

# 备份数据库
backup_database() {
    local timestamp="$1"
    
    if ! read_env_from_container; then
        return 1
    fi
    
    if ! test_database_connection; then
        return 1
    fi
    
    local backup_file="$DB_BACKUP_DIR/database_${timestamp}.sql"
    
    log_info "备份数据库: $DB_DATABASE"
    
    # 创建临时MySQL配置文件以安全传递密码
    local mysql_config_file=$(mktemp /tmp/mysql_backup_config.XXXXXX)
    
    # 设置清理陷阱，直接使用命令而不是函数
    trap "[ -f '$mysql_config_file' ] && rm -f '$mysql_config_file'" EXIT INT TERM
    
    # 写入MySQL配置
    cat > "$mysql_config_file" << EOF
[client]
user=$DB_USERNAME
password=$DB_PASSWORD
EOF
    
    # 设置配置文件权限（仅当前用户可读）
    chmod 600 "$mysql_config_file"
    
    # 将配置文件复制到容器中
    local container_config_file="/tmp/mysql_backup_config_$(date +%s)"
    docker cp "$mysql_config_file" "$MYSQL_CONTAINER:$container_config_file"
    
    # 通过 MySQL 容器执行备份
    if docker exec "$MYSQL_CONTAINER" mysqldump \
        --defaults-extra-file="$container_config_file" \
        --single-transaction \
        --routines \
        --triggers \
        --add-drop-database \
        --create-options \
        --no-tablespaces \
        "$DB_DATABASE" > "$backup_file"; then
        
        # 清理容器中的配置文件
        docker exec "$MYSQL_CONTAINER" rm -f "$container_config_file" 2>/dev/null || true
        
        # 压缩备份文件
        log_info "压缩数据库备份文件..."
        if command -v gzip >/dev/null 2>&1; then
            gzip "$backup_file"
            backup_file="${backup_file}.gz"
            log_info "备份文件已压缩: $backup_file"
        fi
        
        # 创建备份信息文件
        local info_file="$DB_BACKUP_DIR/database_${timestamp}.info"
        cat > "$info_file" << EOF
备份时间: $(date '+%Y-%m-%d %H:%M:%S')
容器名称: $MYSQL_CONTAINER
数据库类型: $DB_CONNECTION
数据库名称: $DB_DATABASE
主机地址: $DB_HOST:$DB_PORT
备份文件: $backup_file
文件大小: $(stat -c%s "$backup_file" 2>/dev/null || stat -f%z "$backup_file" 2>/dev/null || echo "未知") 字节
MD5校验: $(md5sum "$backup_file" 2>/dev/null | cut -d' ' -f1 || md5 -q "$backup_file" 2>/dev/null || echo "未计算")
EOF
        
        log_success "数据库备份完成: $backup_file"
        return 0
    else
        # 清理容器中的配置文件
        docker exec "$MYSQL_CONTAINER" rm -f "$container_config_file" 2>/dev/null || true
        log_error "数据库备份失败"
        return 1
    fi
}

# 恢复 .env 文件
restore_env_file() {
    local backup_file="$1"
    
    if [ ! -f "$backup_file" ]; then
        log_error "备份文件不存在: $backup_file"
        return 1
    fi
    
    if ! check_container "$PHP_CONTAINER"; then
        return 1
    fi
    
    # 备份当前容器中的文件
    local current_backup="/tmp/env_restore_backup_$(get_timestamp)"
    if docker cp "$PHP_CONTAINER:$CONTAINER_BACKEND_DIR/.env" "$current_backup" 2>/dev/null; then
        log_info "当前 .env 文件已备份到本地: $current_backup"
    fi
    
    # 恢复文件到容器
    log_info "恢复 .env 文件到容器..."
    if docker cp "$backup_file" "$PHP_CONTAINER:$CONTAINER_BACKEND_DIR/.env"; then
        # 修正容器中的文件权限
        docker exec "$PHP_CONTAINER" chown www-data:www-data "$CONTAINER_BACKEND_DIR/.env"
        docker exec "$PHP_CONTAINER" chmod 644 "$CONTAINER_BACKEND_DIR/.env"
        
        log_success ".env 文件恢复完成"
        
        # 清理容器缓存
        log_info "清理 Laravel 缓存..."
        docker exec "$PHP_CONTAINER" php "$CONTAINER_BACKEND_DIR/artisan" config:clear
        docker exec "$PHP_CONTAINER" php "$CONTAINER_BACKEND_DIR/artisan" cache:clear
        
        # 验证恢复后的文件
        if read_env_from_container; then
            log_success "恢复的 .env 文件配置验证通过"
        else
            log_warning "恢复的 .env 文件配置可能有问题，请手动检查"
        fi
        
        return 0
    else
        log_error "无法恢复文件到容器"
        return 1
    fi
}

# 恢复数据库
restore_database() {
    local backup_file="$1"
    
    if [ ! -f "$backup_file" ]; then
        log_error "数据库备份文件不存在: $backup_file"
        return 1
    fi
    
    if ! read_env_from_container; then
        return 1
    fi
    
    if ! test_database_connection; then
        return 1
    fi
    
    log_warning "警告：恢复数据库将覆盖容器中数据库 '$DB_DATABASE' 的所有数据！"
    log_prompt "确认恢复数据库？这将删除当前所有数据！(y/N): "
    read -r confirm
    
    if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
        log_info "数据库恢复已取消"
        return 0
    fi
    
    log_info "开始恢复数据库: $DB_DATABASE"
    
    # 创建临时MySQL配置文件以安全传递密码
    local mysql_config_file=$(mktemp /tmp/mysql_restore_config.XXXXXX)
    
    # 设置清理陷阱，直接使用命令而不是函数
    trap "[ -f '$mysql_config_file' ] && rm -f '$mysql_config_file'" EXIT INT TERM
    
    # 写入MySQL配置
    cat > "$mysql_config_file" << EOF
[client]
user=$DB_USERNAME
password=$DB_PASSWORD
EOF
    
    # 设置配置文件权限（仅当前用户可读）
    chmod 600 "$mysql_config_file"
    
    # 将配置文件复制到容器中
    local container_config_file="/tmp/mysql_restore_config_$(date +%s)"
    docker cp "$mysql_config_file" "$MYSQL_CONTAINER:$container_config_file"
    
    # 检查文件是否压缩
    if [[ "$backup_file" == *.gz ]]; then
        log_info "检测到压缩文件，解压后恢复..."
        # 解压并通过管道恢复
        if gunzip -c "$backup_file" | docker exec -i "$MYSQL_CONTAINER" mysql \
            --defaults-extra-file="$container_config_file" "$DB_DATABASE"; then
            log_success "数据库恢复完成"
        else
            # 清理容器中的配置文件
            docker exec "$MYSQL_CONTAINER" rm -f "$container_config_file" 2>/dev/null || true
            log_error "数据库恢复失败"
            return 1
        fi
    else
        # 直接恢复
        if docker exec -i "$MYSQL_CONTAINER" mysql \
            --defaults-extra-file="$container_config_file" "$DB_DATABASE" < "$backup_file"; then
            log_success "数据库恢复完成"
        else
            # 清理容器中的配置文件
            docker exec "$MYSQL_CONTAINER" rm -f "$container_config_file" 2>/dev/null || true
            log_error "数据库恢复失败"
            return 1
        fi
    fi
    
    # 清理容器中的配置文件
    docker exec "$MYSQL_CONTAINER" rm -f "$container_config_file" 2>/dev/null || true
    
    # 验证恢复
    log_info "验证数据库恢复结果..."
    if test_database_connection; then
        log_success "数据库恢复验证通过"
    else
        log_warning "数据库恢复验证失败，请手动检查"
    fi
    
    return 0
}

# 列出备份文件
list_backups() {
    echo
    echo "==============================================="
    echo "               备份文件列表"
    echo "==============================================="
    echo
    
    # 列出 .env 备份
    echo "🔧 .env 文件备份:"
    if [ -d "$ENV_BACKUP_DIR" ] && [ "$(ls -A "$ENV_BACKUP_DIR"/*.backup 2>/dev/null)" ]; then
        for backup in "$ENV_BACKUP_DIR"/*.backup; do
            if [ -f "$backup" ]; then
                local basename=$(basename "$backup" .backup)
                local timestamp=${basename#env_}
                local info_file="$ENV_BACKUP_DIR/${basename}.info"
                
                echo "  📁 $timestamp"
                echo "     文件: $backup"
                if [ -f "$info_file" ]; then
                    local backup_time=$(grep "备份时间:" "$info_file" | cut -d':' -f2- | sed 's/^ *//')
                    local file_size=$(grep "文件大小:" "$info_file" | cut -d':' -f2 | sed 's/^ *//')
                    local container=$(grep "容器名称:" "$info_file" | cut -d':' -f2 | sed 's/^ *//')
                    echo "     时间: $backup_time"
                    echo "     大小: $file_size"
                    echo "     容器: $container"
                fi
                echo
            fi
        done
    else
        echo "  暂无 .env 备份文件"
        echo
    fi
    
    # 列出数据库备份
    echo "🗄️  数据库备份:"
    if [ -d "$DB_BACKUP_DIR" ] && [ "$(ls -A "$DB_BACKUP_DIR"/*.sql* 2>/dev/null)" ]; then
        for backup in "$DB_BACKUP_DIR"/database_*.sql*; do
            if [ -f "$backup" ]; then
                local basename=$(basename "$backup")
                local timestamp
                if [[ "$basename" == *.sql.gz ]]; then
                    timestamp=${basename#database_}
                    timestamp=${timestamp%.sql.gz}
                else
                    timestamp=${basename#database_}
                    timestamp=${timestamp%.sql}
                fi
                
                local info_file="$DB_BACKUP_DIR/database_${timestamp}.info"
                
                echo "  📁 $timestamp"
                echo "     文件: $backup"
                if [ -f "$info_file" ]; then
                    local backup_time=$(grep "备份时间:" "$info_file" | cut -d':' -f2- | sed 's/^ *//')
                    local file_size=$(grep "文件大小:" "$info_file" | cut -d':' -f2 | sed 's/^ *//')
                    local db_name=$(grep "数据库名称:" "$info_file" | cut -d':' -f2 | sed 's/^ *//')
                    local container=$(grep "容器名称:" "$info_file" | cut -d':' -f2 | sed 's/^ *//')
                    echo "     时间: $backup_time"
                    echo "     大小: $file_size"
                    echo "     数据库: $db_name"
                    echo "     容器: $container"
                fi
                echo
            fi
        done
    else
        echo "  暂无数据库备份文件"
        echo
    fi
    
    echo "==============================================="
}

# 验证备份完整性
verify_backup() {
    local backup_type="$1"
    local timestamp="$2"
    
    if [ "$backup_type" = "env" ]; then
        local backup_file="$ENV_BACKUP_DIR/env_${timestamp}.backup"
        local info_file="$ENV_BACKUP_DIR/env_${timestamp}.info"
        
        if [ ! -f "$backup_file" ]; then
            log_error ".env 备份文件不存在: $backup_file"
            return 1
        fi
        
        log_info "验证 .env 备份文件: $timestamp"
        
        # 检查文件大小
        local current_size=$(stat -c%s "$backup_file" 2>/dev/null || stat -f%z "$backup_file" 2>/dev/null)
        if [ -f "$info_file" ]; then
            local recorded_size=$(grep "文件大小:" "$info_file" | cut -d':' -f2 | sed 's/[^0-9]//g')
            if [ -n "$recorded_size" ] && [ "$current_size" != "$recorded_size" ]; then
                log_error "文件大小不匹配！记录: $recorded_size, 实际: $current_size"
                return 1
            fi
        fi
        
        # 检查 MD5
        local current_md5=$(md5sum "$backup_file" 2>/dev/null | cut -d' ' -f1 || md5 -q "$backup_file" 2>/dev/null)
        if [ -f "$info_file" ] && [ -n "$current_md5" ]; then
            local recorded_md5=$(grep "MD5校验:" "$info_file" | cut -d':' -f2 | sed 's/^ *//')
            if [ -n "$recorded_md5" ] && [ "$recorded_md5" != "未计算" ] && [ "$current_md5" != "$recorded_md5" ]; then
                log_error "MD5校验不匹配！记录: $recorded_md5, 实际: $current_md5"
                return 1
            fi
        fi
        
        log_success ".env 备份文件验证通过"
        
    elif [ "$backup_type" = "database" ]; then
        local backup_file_sql="$DB_BACKUP_DIR/database_${timestamp}.sql"
        local backup_file_gz="$DB_BACKUP_DIR/database_${timestamp}.sql.gz"
        local info_file="$DB_BACKUP_DIR/database_${timestamp}.info"
        local backup_file=""
        
        if [ -f "$backup_file_gz" ]; then
            backup_file="$backup_file_gz"
        elif [ -f "$backup_file_sql" ]; then
            backup_file="$backup_file_sql"
        else
            log_error "数据库备份文件不存在: $backup_file_sql 或 $backup_file_gz"
            return 1
        fi
        
        log_info "验证数据库备份文件: $timestamp"
        
        # 检查文件大小
        local current_size=$(stat -c%s "$backup_file" 2>/dev/null || stat -f%z "$backup_file" 2>/dev/null)
        if [ -f "$info_file" ]; then
            local recorded_size=$(grep "文件大小:" "$info_file" | cut -d':' -f2 | sed 's/[^0-9]//g')
            if [ -n "$recorded_size" ] && [ "$current_size" != "$recorded_size" ]; then
                log_error "文件大小不匹配！记录: $recorded_size, 实际: $current_size"
                return 1
            fi
        fi
        
        # 检查 MD5
        local current_md5=$(md5sum "$backup_file" 2>/dev/null | cut -d' ' -f1 || md5 -q "$backup_file" 2>/dev/null)
        if [ -f "$info_file" ] && [ -n "$current_md5" ]; then
            local recorded_md5=$(grep "MD5校验:" "$info_file" | cut -d':' -f2 | sed 's/^ *//')
            if [ -n "$recorded_md5" ] && [ "$recorded_md5" != "未计算" ] && [ "$current_md5" != "$recorded_md5" ]; then
                log_error "MD5校验不匹配！记录: $recorded_md5, 实际: $current_md5"
                return 1
            fi
        fi
        
        # 检查 SQL 文件内容（简单验证）
        if [[ "$backup_file" == *.gz ]]; then
            if ! gunzip -t "$backup_file" 2>/dev/null; then
                log_error "压缩文件损坏！"
                return 1
            fi
            # 检查解压后的内容
            if ! gunzip -c "$backup_file" | head -10 | grep -q "MySQL dump"; then
                log_warning "备份文件可能不是有效的 MySQL 转储文件"
            fi
        else
            if ! head -10 "$backup_file" | grep -q "MySQL dump"; then
                log_warning "备份文件可能不是有效的 MySQL 转储文件"
            fi
        fi
        
        log_success "数据库备份文件验证通过"
    else
        log_error "未知的备份类型: $backup_type"
        return 1
    fi
    
    return 0
}

# 显示帮助信息
show_help() {
    echo
    echo "SSL证书管理系统 - Keeper (数据守护脚本) Docker版"
    echo "专门用于容器化环境中后端 .env 文件和数据库的备份与恢复"
    echo
    echo "用法: $0 [命令] [选项]"
    echo
    echo "命令:"
    echo "  backup                      - 同时备份 .env 和数据库"
    echo "  backup-env                  - 仅备份 .env 文件"
    echo "  backup-db                   - 仅备份数据库"
    echo "  restore-env [时间戳]        - 恢复 .env 文件"
    echo "  restore-db [时间戳]         - 恢复数据库"
    echo "  list                        - 列出所有备份文件"
    echo "  verify [类型] [时间戳]      - 验证备份完整性"
    echo "  help                        - 显示此帮助信息"
    echo
    echo "示例:"
    echo "  $0 backup                   # 完整备份"
    echo "  $0 backup-env               # 仅备份配置文件"
    echo "  $0 backup-db                # 仅备份数据库"
    echo "  $0 restore-env 20240122_143022    # 恢复指定时间的配置"
    echo "  $0 restore-db 20240122_143022     # 恢复指定时间的数据库"
    echo "  $0 verify env 20240122_143022     # 验证配置备份"
    echo "  $0 verify database 20240122_143022 # 验证数据库备份"
    echo "  $0 list                     # 查看所有备份"
    echo
    echo "说明:"
    echo "• 备份文件存储在: $BACKUP_ROOT_DIR"
    echo "• 时间戳格式: YYYYMMDD_HHMMSS (例如: 20240122_143022)"
    echo "• 恢复前会自动备份当前文件"
    echo "• 数据库恢复前会提示确认"
    echo "• 需要确保 Docker 容器正在运行"
    echo
    echo "容器说明:"
    echo "• PHP 容器: $PHP_CONTAINER"
    echo "• MySQL 容器: $MYSQL_CONTAINER"
    echo "• 后端目录: $CONTAINER_BACKEND_DIR"
    echo
}

# 主函数
main() {
    local command="${1:-help}"
    
    case "$command" in
        "backup")
            log_info "开始完整备份（.env + 数据库）..."
            local timestamp=$(get_timestamp)
            
            if backup_env_file "$timestamp" && backup_database "$timestamp"; then
                log_success "完整备份成功完成！时间戳: $timestamp"
                echo
                echo "备份文件位置:"
                echo "• .env: $ENV_BACKUP_DIR/env_${timestamp}.backup"
                echo "• 数据库: $DB_BACKUP_DIR/database_${timestamp}.sql*"
                echo
            else
                log_error "备份过程中出现错误"
                return 1
            fi
            ;;
            
        "backup-env")
            log_info "开始备份 .env 文件..."
            local timestamp=$(get_timestamp)
            
            if backup_env_file "$timestamp"; then
                log_success ".env 文件备份完成！时间戳: $timestamp"
                echo "备份文件: $ENV_BACKUP_DIR/env_${timestamp}.backup"
            else
                log_error ".env 文件备份失败"
                return 1
            fi
            ;;
            
        "backup-db")
            log_info "开始备份数据库..."
            local timestamp=$(get_timestamp)
            
            if backup_database "$timestamp"; then
                log_success "数据库备份完成！时间戳: $timestamp"
                echo "备份文件: $DB_BACKUP_DIR/database_${timestamp}.sql*"
            else
                log_error "数据库备份失败"
                return 1
            fi
            ;;
            
        "restore-env")
            local timestamp="$2"
            
            if [ -z "$timestamp" ]; then
                log_error "请指定要恢复的时间戳"
                echo "用法: $0 restore-env [时间戳]"
                echo "使用 '$0 list' 查看可用的备份"
                return 1
            fi
            
            local backup_file="$ENV_BACKUP_DIR/env_${timestamp}.backup"
            
            if restore_env_file "$backup_file"; then
                log_success ".env 文件恢复完成！"
            else
                log_error ".env 文件恢复失败"
                return 1
            fi
            ;;
            
        "restore-db")
            local timestamp="$2"
            
            if [ -z "$timestamp" ]; then
                log_error "请指定要恢复的时间戳"
                echo "用法: $0 restore-db [时间戳]"
                echo "使用 '$0 list' 查看可用的备份"
                return 1
            fi
            
            local backup_file_sql="$DB_BACKUP_DIR/database_${timestamp}.sql"
            local backup_file_gz="$DB_BACKUP_DIR/database_${timestamp}.sql.gz"
            local backup_file=""
            
            if [ -f "$backup_file_gz" ]; then
                backup_file="$backup_file_gz"
            elif [ -f "$backup_file_sql" ]; then
                backup_file="$backup_file_sql"
            else
                log_error "数据库备份文件不存在: $backup_file_sql 或 $backup_file_gz"
                return 1
            fi
            
            if restore_database "$backup_file"; then
                log_success "数据库恢复完成！"
            else
                log_error "数据库恢复失败"
                return 1
            fi
            ;;
            
        "list")
            list_backups
            ;;
            
        "verify")
            local backup_type="$2"
            local timestamp="$3"
            
            if [ -z "$backup_type" ] || [ -z "$timestamp" ]; then
                log_error "请指定备份类型和时间戳"
                echo "用法: $0 verify [env|database] [时间戳]"
                echo "使用 '$0 list' 查看可用的备份"
                return 1
            fi
            
            if verify_backup "$backup_type" "$timestamp"; then
                log_success "备份验证通过！"
            else
                log_error "备份验证失败"
                return 1
            fi
            ;;
            
        "help"|"-h")
            show_help
            ;;
            
        *)
            log_error "未知命令: $command"
            echo
            show_help
            return 1
            ;;
    esac
}

# 检查依赖工具
check_dependencies() {
    local missing_tools=()
    
    # 检查 Docker
    if ! command -v docker >/dev/null 2>&1; then
        missing_tools+=("docker")
    fi
    
    # 检查 docker compose
    if ! docker compose version >/dev/null 2>&1; then
        if ! docker-compose version >/dev/null 2>&1; then
            missing_tools+=("docker-compose")
        fi
    fi
    
    if [ ${#missing_tools[@]} -gt 0 ]; then
        log_error "缺少必要的工具: ${missing_tools[*]}"
        log_error "请先安装 Docker 和 Docker Compose"
        return 1
    fi
    
    return 0
}

# 运行前置检查
if ! check_dependencies; then
    exit 1
fi

# 运行主函数
main "$@"